/*
 * G2P_PronunStruct.cpp
 *
 *  Created on: Nov 21, 2012
 *      Author: Pongsathon Janyoi
 */
#include "g2p_pronun_struct.h"
#include <strings.h>
pronun_struct ** pron_st;
int pron_st_len = 0;

char ci_map[20][5] = { "p", "t", "c", "k", "z", "ph", "th", "kh", "b", "d", "m",
		"n", "ng", "l", "f", "s", "h", "w", "j" };
char ci_map_phonetic[20][10] = { "p", "t", "c", "k", "\u0294\u034f", "p\u02b0",
		"t\u02b0", "k\u02b0", "b", "d", "m", "n", "\u014b", "l", "f", "s", "h",
		"w", "j" };
char v_map[25][5] = { "a", "aa", "i", "ii", "v", "vv", "u", "uu", "e", "ee",
		"x", "xx", "o", "oo", "@", "@@", "q", "qq", "ia", "iia", "va", "vva",
		"ua", "uua" };
char v_map_phonetic[25][20] = { "%sa%s", "%sa%s\u02d0", "%si%s", "%si%s\u02d0",
		"%s\u026f%s", "%s\u026f%s\u02d0", "%su%s", "%su%s\u02d0", "%se%s",
		"%se%s\u02d0", "%s\u025b%s", "%s\u025b%s\u02d0", "%so%s", "%so%s\u02d0",
		"%s\u0254%s", "%s\u0254%s\u02d0", "%s\u0259%s", "%s\u0259%s\u02d0",
		"%si%sa", "%si%s\u02d0a\u02d0", "%s\u026f%sa",
		"%s\u026f%s\u02d0a\u02d0", "%su%sa", "%su%s\u02d0a\u02d0" };
char cf_map[10][5] = { "p^", "t^", "k^", "n^", "m^", "ng^", "j^", "w^", "z^" };

char cf_map_phonetic[10][5] = { "p", "t", "k", "n", "m", "\u014b", "y", "w",
		"\u0294" };

char tone_map_phonetic[10][10] = { "", "\u0340", "\u0302", "\u0341", "\u030c",
		"" };
int pronun_struct_make_binary(const char * input, const char * output) {
	printf("Create Index Binary Structure.\n");
	printf("Text Input : %s", input);
	printf("Binary Output : %s", output);

	FILE * fp = fopen(input, "r");
	FILE * fw = fopen(output, "wb");

	char prefix[100];
	char number[100];
	while (!feof(fp)) {
		fscanf(fp, "%s\t%s\n", prefix, number);
		unsigned int n = atoi(number);
		char d = prefix[0];
		printf("%d\t%d\n", d, n);
		struc_unit st;
		st.number = n;
		st.prefix = d;
		fwrite(&st, sizeof(struc_unit), 1, fw);

	}
	fclose(fp);
	fclose(fw);

	return 0;
}
int pronun_struct_load_binary(const char* input) {
	pron_st = (pronun_struct **) calloc(30000, sizeof(pronun_struct *));
	FILE * fp = fopen(input, "r");

	int i = 0;
	unsigned int x[10];
	int c[10];
	int am = 0;
	int size = 0;
	char before = 0;
	while (!feof(fp)) {
		struc_unit st;
		fread(&st, sizeof(struc_unit), 1, fp);

		if (st.prefix == 'B') {
			if (before == 'B') {
				pron_st[i] = (pronun_struct *) malloc(sizeof(pronun_struct));
				pron_st[i]->tri_phone = (unsigned int *) calloc(1,
						sizeof(unsigned int));
				pron_st[i]->tri_phone[0] = x[0];
				pron_st[i]->st = (pronun_struct_unit**) calloc(1,
						sizeof(pronun_struct_unit*));
				pronun_struct_unit* unit = (pronun_struct_unit*) malloc(
						sizeof(pronun_struct_unit));
				unit->sound = 1;
				unit->st1 = x[0];
				unit->c1 = c[0];
				unit->st2 = 99;
				pron_st[i]->st[0] = unit;
				pron_st[i]->st_unit = 1; // one unit one sound
				pron_st[i]->len = 1;
				i++;
			}
			if (before == 'I' || before == 'N') {

				pron_st[i] = (pronun_struct *) malloc(sizeof(pronun_struct));
				pron_st[i]->tri_phone = (unsigned int *) calloc(am,
						sizeof(unsigned int));
				for (int k = 0; k < am; k++) {
					pron_st[i]->tri_phone[k] = x[k];
					//printf("\nx [%d] %d",k,x[k]);
				}
				pron_st[i]->st = (pronun_struct_unit**) calloc(am,
						sizeof(pronun_struct_unit*));
				pron_st[i]->st_unit = 0;
				int _b = 0;
				int _l = 0;
				int k;
				for (k = 0; k < am; k++) {
					if (x[k] == 99) {
						_l = k - _b;
						_b = k + 1;
						//printf("\nL = %d", _l);
						if (_l == 2) {
							//printf("\nx[ %d %d ]", x[k - 2], x[k - 1]);
							pronun_struct_unit* unit =
									(pronun_struct_unit*) malloc(
											sizeof(pronun_struct_unit));
							unit->sound = 2;
							unit->st1 = x[k - 2];
							unit->st2 = x[k - 1];
							unit->c1 = c[k - 2];
							unit->c2 = c[k - 1];
							pron_st[i]->st[pron_st[i]->st_unit++] = unit;
						} else if (_l == 1) {
							//printf("\nx[ %06d ]", x[k - 1]);
							pronun_struct_unit* unit =
									(pronun_struct_unit*) malloc(
											sizeof(pronun_struct_unit));
							unit->sound = 1;
							unit->st1 = x[k - 1];
							unit->c1 = c[k - 1];
							unit->st2 = 99;

							pron_st[i]->st[pron_st[i]->st_unit++] = unit;
						}
					}
				}
				//printf("\n_b = %d k = %d _l = %d",_b,k,k-_b);

				_l = k - _b;
				//printf("\naL = %d", _l);
				if (_l == 2) {
					//printf("\nx[ %06d %06d ]", x[k - 2], x[k - 1]);
					pronun_struct_unit* unit = (pronun_struct_unit*) malloc(
							sizeof(pronun_struct_unit));
					unit->sound = 2;
					unit->st1 = x[k - 2];
					unit->st2 = x[k - 1];
					unit->c1 = c[k - 2];
					unit->c2 = c[k - 1];
					pron_st[i]->st[pron_st[i]->st_unit++] = unit;
				} else if (_l == 1) {
					//printf("\nx[ %06d ]", x[k - 1]);
					pronun_struct_unit* unit = (pronun_struct_unit*) malloc(
							sizeof(pronun_struct_unit));
					unit->sound = 1;
					unit->st1 = x[k - 1];
					unit->c1 = c[k - 1];
					unit->st2 = 99;
					pron_st[i]->st[pron_st[i]->st_unit++] = unit;
				}

				pron_st[i]->len = am;
				i++;
			}
			x[0] = st.number % 1000000;
			c[0] = st.number / 1000000;
			am = 1;
			size = 1;
			before = 'B';
			//printf("\nNew St.");
		} else {
			if (st.prefix == 'N') {
				x[am] = 99;
				c[am] = 0;
				am++;
				x[am] = st.number % 1000000;
				c[am] = st.number / 1000000;
				am++;
				before = 'N';
				size++;
			} else if (st.prefix == 'I') {
				x[am] = st.number % 1000000;
				c[am] = st.number / 1000000;
				am++;
				before = 'I';
			}
		}
	}

	pron_st_len = i;
	/*
	 printf("\ni = %d", i);
	 for (int i = 0; i < pron_st_len; i++) {
	 printf("ID : %d St :", i);
	 for (int j = 0; j < pron_st[i]->st_unit; j++) {
	 printf(" %d",pron_st[i]->tri_phone[j]);
	 printf(" %d %d c=%d %d", pron_st[i]->st[j]->st1, pron_st[i]->st[j]->st2,pron_st[i]->st[j]->c1,pron_st[i]->st[j]->c2);
	 }
	 printf("\n");
	 }
	 */
	printf("\nLoad Succeed.");
}
pronun_struct * pronun_struct_find(int index) {
	if (index < 0 || index > pron_st_len) {
		return NULL;
	} else {
		//pronun_struct_print(pron_st[index]);
		return pron_st[index];
	}
}

void pronun_sturct_num2phone(char * text, int num, int tone) {
	if (num != 99) {
		int ic, v, fc;
		int tnum = num;
		int r;
		int s;
		r = num / 100;
		s = num % 100;
		fc = s;

		s = r % 100;
		r = r / 100;
		v = s;

		ic = r % 100;
		//printf("\n%d-%d-%d", ic, v, fc);
		sprintf(text, "%s-%s-%s-%d", ci_map[ic], v_map[v], cf_map[fc], tone);
	}
}
void pronun_sturct_num2phonetic(char * text, int num, int tone) {

	int ic, v, fc;
	int tnum = num;
	int r;
	int s;
	r = num / 100;
	s = num % 100;
	fc = s;

	s = r % 100;
	r = r / 100;
	v = s;

	ic = r;

	char ve[50] = "";
	if (tone % 2 == 1) {
		sprintf(ve, v_map_phonetic[v], "", tone_map_phonetic[tone]);
	} else {
		sprintf(ve, v_map_phonetic[v], tone_map_phonetic[tone], "");
	}
	sprintf(text, "%s%s%s", ci_map_phonetic[ic], ve, cf_map_phonetic[fc]);

}
void pronun_struct_print(pronun_struct * stc) {
	if (stc == NULL) {
		printf("\Struct NULL");
	} else {
		if (stc->st != NULL) {
			printf("\n[N:%d]", stc->st_unit);
			for (int i = 0; i < stc->st_unit; i++) {
				printf("\n%d)%d Snd %06d | %06d | ", i + 1, stc->st[i]->sound,
						stc->st[i]->st1, stc->st[i]->st2);
				char * mtext = (char *) calloc(500, sizeof(char));
				pronun_sturct_num2phone(mtext, (int) stc->st[i]->st1, 0);
				printf("--> %s", mtext);
				sprintf(mtext,"");
				pronun_sturct_num2phone(mtext, (int) stc->st[i]->st2, 0);
				printf(" %s", mtext);
				free(mtext);

			}
		}
		/*
		 if (st->tri_phone != NULL) {
		 printf("\nPhone :");
		 for (int i = 0; i < st->len; i++) {
		 if (st->tri_phone[i] == 99) {
		 printf(",");
		 } else {
		 printf(" %6d ", st->tri_phone[i]);
		 }
		 }
		 for (int i = 0; i < st->len; i++) {
		 if (st->tri_phone[i] == 99) {
		 printf(",");
		 } else {
		 char *mtext = (char *) calloc(500, sizeof(char));

		 pronun_sturct_num2phone(mtext, st->tri_phone[i]);
		 printf(" %d --> %s ", st->tri_phone[i], mtext);
		 free(mtext);
		 }
		 }
		 } else {
		 printf("\nstruct tri NULL");
		 }
		 */
	}
}

